using Microsoft.SqlServer.Management.Common;
using Microsoft.SqlServer.Management.Sdk.Sfc;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Tools.PublishWizard.Helpers;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Text;

namespace Microsoft.SqlServer.Management.SqlManagerUI.Scripting
{
using Server = Microsoft.SqlServer.Management.Smo.Server;
	internal class ScriptingDriver : IDisposable
	{
		internal const int BATCH_SIZE = 100;

		public EventHandler<ProgressEventArgs> ProgressEvent;

		private string _databaseName;

		private ScriptDestination _destination = ScriptDestination.SingleFile;

		private bool _schemaQualify = true;

		private string _webServiceAddress;

		private string _webServiceUserName;

		private string _webServicePassword;

		private string _webServiceSqlServerName;

		private string _webServiceSqlDatabaseName;

		private string _webServiceSqlUserName;

		private string _webServiceSqlPassword;

		private SqlServerVersion _targetServerVersion = SqlServerVersion.Version80;

		private ServerConnection _serverConnection;

		private string _outputPath;

		private bool _overwriteExisting;

		private bool _dataOnly;

		private bool _schemaOnly;

		private bool _dropExisting = true;

		private bool _useTransactionForPublish = true;

		private List<Urn> _urns;

		private Dictionary<string, Urn> _namesOfRolesAndUsers;

		public ServerConnection ServerConnection
		{
			get
			{
				return this._serverConnection;
			}
		}

		public Server ServerObject
		{
			get
			{
				return new Server(this._serverConnection);
			}
		}

		public string DatabaseName
		{
			get
			{
				return this._databaseName;
			}
			set
			{
				this._namesOfRolesAndUsers = null;
				this.Urns.Clear();
				this._databaseName = value;
			}
		}

		public bool SchemaQualify
		{
			get
			{
				return this._schemaQualify;
			}
			set
			{
				this._schemaQualify = value;
			}
		}

		public ScriptDestination Destination
		{
			get
			{
				return this._destination;
			}
			set
			{
                //if (value != ScriptDestination.PublishToWeb && value != ScriptDestination.SingleFile)
                //{
                //    throw new InvalidOperationException("Only scripting to file and web is supported");
                //}
				this._destination = value;
			}
		}

		public string WebServiceAddress
		{
			get
			{
				return this._webServiceAddress;
			}
			set
			{
				this._webServiceAddress = value;
			}
		}

		public string WebServiceUserName
		{
			get
			{
				return this._webServiceUserName;
			}
			set
			{
				this._webServiceUserName = value;
			}
		}

		public string WebServicePassword
		{
			get
			{
				return this._webServicePassword;
			}
			set
			{
				this._webServicePassword = value;
			}
		}

		public string WebServiceSqlServerName
		{
			get
			{
				return this._webServiceSqlServerName;
			}
			set
			{
				this._webServiceSqlServerName = value;
			}
		}

		public string WebServiceSqlDatabaseName
		{
			get
			{
				return this._webServiceSqlDatabaseName;
			}
			set
			{
				this._webServiceSqlDatabaseName = value;
			}
		}

		public string WebServiceSqlUserName
		{
			get
			{
				return this._webServiceSqlUserName;
			}
			set
			{
				this._webServiceSqlUserName = value;
			}
		}

		public string WebServiceSqlPassword
		{
			get
			{
				return this._webServiceSqlPassword;
			}
			set
			{
				this._webServiceSqlPassword = value;
			}
		}

		public string OutputPath
		{
			get
			{
				TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
				return this._outputPath;
			}
			set
			{
				TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
				this.VerifyDisposeNotCalled();
				if (value == null)
				{
					throw new ArgumentNullException("OutputPath");
				}
				this._outputPath = value;
			}
		}

		public SqlServerVersion TargetServerVersion
		{
			get
			{
				return this._targetServerVersion;
			}
			set
			{
				this._targetServerVersion = value;
			}
		}

		public bool OverwriteExisting
		{
			get
			{
				TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
				return this._overwriteExisting;
			}
			set
			{
				TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
				this.VerifyDisposeNotCalled();
				this._overwriteExisting = value;
			}
		}

		public bool DataOnly
		{
			get
			{
				TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
				return this._dataOnly;
			}
			set
			{
				TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
				this.VerifyDisposeNotCalled();
				this._dataOnly = value;
			}
		}

		public bool DropExistingObjects
		{
			get
			{
				return this._dropExisting;
			}
			set
			{
				this._dropExisting = value;
			}
		}

		public bool UseTransactionForPublish
		{
			get
			{
				return this._useTransactionForPublish;
			}
			set
			{
				this._useTransactionForPublish = value;
			}
		}

		public bool SchemaOnly
		{
			get
			{
				TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
				return this._schemaOnly;
			}
			set
			{
				TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
				this.VerifyDisposeNotCalled();
				this._schemaOnly = value;
			}
		}

		internal List<Urn> Urns
		{
			get
			{
				if (this._urns == null)
				{
					this._urns = new List<Urn>();
				}
				return this._urns;
			}
		}

		public ScriptingDriver(string connectionString)
		{
			TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
			ArgumentValidationHelpers.ValidateStringNotNullOrEmpty(connectionString, "connectionString");
			SqlConnectionStringBuilder sqlConnectionStringBuilder = null;
			try
			{
				sqlConnectionStringBuilder = new SqlConnectionStringBuilder(connectionString);
			}
			catch (ArgumentException)
			{
				throw new ArgumentException(ScriptingEngineResources.ERROR_InvalidConnectionString);
			}
			this._serverConnection = new ServerConnection(new SqlConnection(sqlConnectionStringBuilder.ConnectionString));
			if (!string.IsNullOrEmpty(sqlConnectionStringBuilder.InitialCatalog))
			{
				this.DatabaseName = sqlConnectionStringBuilder.InitialCatalog;
			}
			else if (!string.IsNullOrEmpty(sqlConnectionStringBuilder.AttachDBFilename) && sqlConnectionStringBuilder.UserInstance)
			{
				this._serverConnection.Connect();
				this.DatabaseName = this._serverConnection.SqlConnectionObject.Database;
				this._serverConnection.Disconnect();
				if (string.IsNullOrEmpty(this.DatabaseName))
				{
					this.DatabaseName = sqlConnectionStringBuilder.AttachDBFilename;
				}
			}
			this.ConnectToServer();
			this.InitializeOutputPath();
		}

		public ScriptingDriver(string databaseName, string userName, string password)
		{
			TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
			ArgumentValidationHelpers.ValidateStringNotNullOrEmpty(userName, "userName");
			ArgumentValidationHelpers.ValidateNotNull(password, "password");
			this.DatabaseName = databaseName;
			this.InitializeServerConnection(databaseName, "(local)", userName, password);
			this.InitializeOutputPath();
		}

		public ScriptingDriver(string databaseName, string serverName)
		{
			TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
			ArgumentValidationHelpers.ValidateStringNotNullOrEmpty(serverName, "serverName");
			this.DatabaseName = databaseName;
			this.InitializeServerConnection(databaseName, serverName, null, null);
			this.InitializeOutputPath();
		}

		public ScriptingDriver(string databaseName, string serverName, string userName, string password)
		{
			TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
			ArgumentValidationHelpers.ValidateStringNotNullOrEmpty(serverName, "serverName");
			ArgumentValidationHelpers.ValidateStringNotNullOrEmpty(userName, "userName");
			ArgumentValidationHelpers.ValidateNotNull(password, "password");
			this.DatabaseName = databaseName;
			this.InitializeServerConnection(databaseName, serverName, userName, password);
			this.InitializeOutputPath();
		}

		public void GenerateScript()
		{
			TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
			if (string.IsNullOrEmpty(this.DatabaseName))
			{
				throw new ArgumentException(ScriptingEngineResources.ERROR_DatabaseNotPresentInConnectionString);
			}
			this.VerifyDisposeNotCalled();
			this.VerifySchemOnlyAndDataOnly();
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			ScriptingOptions scriptingOptions = this.GetScriptingOptions();
			Urn[] listOfObjectUrns = this.GetListOfObjectUrns(scriptingOptions);
			if (listOfObjectUrns.Length == 0)
			{
				this.UpdateProgress(ScriptingEngineResources.NoObjectsToScript);
				return;
			}
			Server server = new Server(this._serverConnection);
			Database database = server.Databases[this.DatabaseName];
			Connection connectionInstance = Connection.ConnectionInstance;
			connectionInstance.Init(database);
			server.SetDefaultInitFields(typeof(UserDefinedFunction), true);
			server.SetDefaultInitFields(typeof(UserDefinedDataType), true);
			database.PrefetchObjects(typeof(Table), scriptingOptions);
			database.PrefetchObjects(typeof(Rule), scriptingOptions);
			database.PrefetchObjects(typeof(StoredProcedure), scriptingOptions);
			database.PrefetchObjects(typeof(View), scriptingOptions);
			database.PrefetchObjects(typeof(Default), scriptingOptions);
			if (ScriptingDriver.IsServerVersionGreaterThan2000(database.Parent))
			{
				database.PrefetchObjects(typeof(UserDefinedAggregate), scriptingOptions);
				database.PrefetchObjects(typeof(XmlSchemaCollection), scriptingOptions);
				database.PrefetchObjects(typeof(SqlAssembly), scriptingOptions);
				database.PrefetchObjects(typeof(UserDefinedType), scriptingOptions);
			}
			ScriptingEngine scriptingEngine = new ScriptingEngine(server);
			scriptingEngine.BatchSeparator = "GO";
			scriptingEngine.Destination = this.Destination;
			switch (scriptingEngine.Destination)
            {
                case ScriptDestination.FilePerObject:
                    scriptingEngine.FileEncoding = Encoding.UTF8;
                    scriptingEngine.FileName = this._outputPath;
                    scriptingEngine.ScriptToFileMode = ScriptToFileMode.Overwrite;
                    goto IL_286;

                case ScriptDestination.SingleFile:
                    scriptingEngine.FileEncoding = Encoding.Unicode;
                    scriptingEngine.FileName = this._outputPath;
                    scriptingEngine.ScriptToFileMode = ScriptToFileMode.Append;
                    if (!File.Exists(this._outputPath))
                    {
                        goto IL_286;
                    }
                    if (this._overwriteExisting)
                    {
                        File.Delete(this._outputPath);
                        goto IL_286;
                    }
                    throw new IOException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_FileExists, new object[]
				{
					this._outputPath
				}));
                case ScriptDestination.PublishToWeb:
                    scriptingEngine.WebServiceAddress = this.WebServiceAddress;
                    scriptingEngine.WebServicePassword = this.WebServicePassword;
                    scriptingEngine.WebServiceUserName = this.WebServiceUserName;
                    scriptingEngine.WebServiceSqlServerName = this.WebServiceSqlServerName;
                    scriptingEngine.WebServiceSqlDatabaseName = this.WebServiceSqlDatabaseName;
                    scriptingEngine.WebServiceSqlUserName = this.WebServiceSqlUserName;
                    scriptingEngine.WebServiceSqlPassword = this.WebServiceSqlPassword;
                    scriptingEngine.UseTransactionForPublish = this.UseTransactionForPublish;
                    goto IL_286;
            }
            //throw new InvalidOperationException("Only scripting to file and web is supported");
			IL_286:
			scriptingEngine.Options = scriptingOptions;
			scriptingEngine.ScriptData = !this.SchemaOnly;
			scriptingEngine.ScriptDropData = this.DataOnly;
			if (!this.DataOnly)
			{
				scriptingEngine.ScriptCreate = true;
				scriptingEngine.ScriptDrop = this.DropExistingObjects;
				scriptingEngine.ScriptPermission = true;
			}
			scriptingEngine.ScriptingProgress += new EventHandler<ScriptingProgressEventArgs>(this.ScriptingProgress);
			scriptingEngine.ObjectScripted += new EventHandler<ObjectScriptedEventArgs>(this.ObjectScripted);
			scriptingEngine.AddRange(listOfObjectUrns);
			IEnumerable<Urn> urnsToScript = scriptingEngine.GetUrnsToScript();
			ScriptingDriver.CheckForInvalidObjects(server, urnsToScript, scriptingEngine.Options);
			if (scriptingEngine.Destination == ScriptDestination.PublishToWeb && scriptingEngine.UseTransactionForPublish)
			{
				this.CheckPublishTransaction(this.TargetServerVersion);
			}
			scriptingEngine.GenerateScript();
			this.UpdateProgress(string.Empty);
			this.UpdateProgress(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.WritingToSingleFileCompleteWithNoOverflow, new object[]
			{
				this.DatabaseName
			}));
			stopwatch.Stop();
			TimeSpan arg_37C_0 = stopwatch.Elapsed;
		}

		public void Dispose()
		{
			TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
			if (this._serverConnection != null)
			{
				this._serverConnection.Disconnect();
				this._serverConnection = null;
			}
		}

		internal void CheckPublishTransaction(SqlServerVersion targetVersion)
		{
			if (this.Urns.Count > 0)
			{
				using (List<Urn>.Enumerator enumerator = this.Urns.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						Urn current = enumerator.Current;
						if (targetVersion == SqlServerVersion.Version80 && (current.Type == "Role" || current.Type == "User"))
						{
							throw new InvalidOperationException(ScriptingEngineResources.ERROR_RoleOrUserOn2000WithTransaction);
						}
						if (current.Type == "FullTextCatalog")
						{
							throw new InvalidOperationException(ScriptingEngineResources.ERROR_FullTextCatalogWithTransaction);
						}
					}
					return;
				}
			}
			Database database = this.ServerObject.Databases[this.DatabaseName];
			if (database.Roles.Count != 0 && database.Users.Count != 0 && targetVersion == SqlServerVersion.Version80)
			{
				throw new InvalidOperationException(ScriptingEngineResources.ERROR_RoleOrUserOn2000WithTransaction);
			}
			int num = 0;
			try
			{
				num = database.FullTextCatalogs.Count;
			}
			catch (UnsupportedFeatureException)
			{
			}
			if (num != 0)
			{
				throw new InvalidOperationException(ScriptingEngineResources.ERROR_FullTextCatalogWithTransaction);
			}
		}

		private void VerifySchemOnlyAndDataOnly()
		{
			if (this.DataOnly && this.SchemaOnly)
			{
				throw new ArgumentException(ScriptingEngineResources.ERROR_SchemaOnlyAndDataOnly);
			}
		}

		private void VerifyDisposeNotCalled()
		{
			if (this._serverConnection == null)
			{
				throw new InvalidOperationException("Cannot perform this operation after calling Dispose");
			}
		}

		private void ScriptingProgress(object sender, ScriptingProgressEventArgs e)
		{
			if (this.ProgressEvent != null)
			{
				if (string.IsNullOrEmpty(e.Message))
				{
					this.ProgressEvent(this, new ProgressEventArgs(ScriptingEngineResources.ProgressReportingCharacter, ProgressEventType.Reporting));
					return;
				}
				this.ProgressEvent(this, new ProgressEventArgs(e.Message, e.EventType));
			}
		}

		private void ObjectScripted(object sender, ObjectScriptedEventArgs e)
		{
			if (this.ProgressEvent != null && e.Action == ScriptActions.Create && e.ObjectInfo.Urn.Type == "ApplicationRole")
			{
				Server server = new Server(this.ServerConnection);
				ApplicationRole applicationRole = server.GetSmoObject(e.ObjectInfo.Urn) as ApplicationRole;
				ScriptingOptions scriptingOptions = this.GetScriptingOptions();
				if (scriptingOptions.TargetServerVersion == SqlServerVersion.Version80)
				{
					this.UpdateProgress(new ProgressEventArgs(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ScriptingApplicationRoleTo2000, new object[]
					{
						applicationRole.Name
					}), ProgressEventType.ObjectInformation));
					return;
				}
				this.UpdateProgress(new ProgressEventArgs(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ScriptingApplicationRoleTo2005, new object[]
				{
					applicationRole.Name
				}), ProgressEventType.ObjectInformation));
			}
		}

		private void UpdateProgress(string progressMessage)
		{
			if (this.ProgressEvent != null)
			{
				this.ProgressEvent(this, new ProgressEventArgs(progressMessage));
			}
		}

		private void UpdateProgress(ProgressEventArgs eventArgs)
		{
			ArgumentValidationHelpers.ValidateNotNull(eventArgs, "eventArgs");
			if (this.ProgressEvent != null)
			{
				this.ProgressEvent(this, eventArgs);
			}
		}

		private void InitializeServerConnection(string databaseName, string serverName, string userName, string password)
		{
			TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
			this._serverConnection = new ServerConnection();
			this._serverConnection.DatabaseName = databaseName;
			this._serverConnection.ServerInstance = serverName;
			if (userName != null)
			{
				this._serverConnection.LoginSecure = false;
				this._serverConnection.Login = userName;
				this._serverConnection.Password = password;
			}
			this.ConnectToServer();
		}

		private static void CheckForInvalidObjects(Server server, IEnumerable<Urn> urns, ScriptingOptions scriptingOptions)
		{
			Type typeFromHandle = typeof(View);
			Type typeFromHandle2 = typeof(SqlAssembly);
			Type typeFromHandle3 = typeof(Table);
			foreach (Urn current in urns)
			{
				SqlSmoObject smoObject = server.GetSmoObject(current);
				bool flag = ScriptingDriver.IsServerVersionGreaterThan2000(server);
				if (smoObject != null)
				{
					Type type = smoObject.GetType();
					if (scriptingOptions.TargetServerVersion == SqlServerVersion.Version80 && typeFromHandle3.IsAssignableFrom(type))
					{
						Table table = (Table)smoObject;
						foreach (Index index in table.Indexes)
						{
							if (index.IndexKeyType == IndexKeyType.DriPrimaryKey && index.IgnoreDuplicateKeys)
							{
								throw new UnsupportedFeatureException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_ScriptingPrimaryKeyWithIgnoreDuplicates, new object[]
								{
									"IGNORE_DUP_KEY",
									ScriptTableCommand.GetTableName(scriptingOptions, table)
								}));
							}
						}
						foreach (Column column in table.Columns)
						{
							if (column.Computed && column.IsForeignKey)
							{
								throw new UnsupportedFeatureException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_TableWithComputedColumnAndConstraintTo2000, new object[]
								{
									column.Name,
									ScriptTableCommand.GetTableName(scriptingOptions, table),
									"Foreign Key"
								}));
							}
						}
					}
					ScriptingDriver.CheckTriggers(flag, scriptingOptions, smoObject, type);
					if (typeFromHandle.IsAssignableFrom(type))
					{
						View view = (View)smoObject;
						if (view.IsEncrypted)
						{
							throw new UnsupportedFeatureException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_ScriptingEncryptedView, new object[]
							{
								view.Name
							}));
						}
					}
					ScriptingDriver.CheckDatabaseRoles(scriptingOptions, smoObject, type);
					ScriptingDriver.CheckSchemas(scriptingOptions, smoObject, type);
					ScriptingDriver.CheckStoredProcedures(flag, scriptingOptions, smoObject, type);
					if (scriptingOptions.TargetServerVersion == SqlServerVersion.Version80 && typeFromHandle2.IsAssignableFrom(type))
					{
						throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_AssembliesNotSupportedOn2000, new object[]
						{
							((SqlAssembly)smoObject).Name
						}));
					}
					ScriptingDriver.CheckUDF(scriptingOptions, smoObject, flag, type);
					ScriptingDriver.CheckUDDTs(scriptingOptions, smoObject, type);
				}
			}
		}

		private static void CheckSchemas(ScriptingOptions scriptingOptions, SqlSmoObject smoObject, Type smoObjectType)
		{
			if (scriptingOptions.TargetServerVersion == SqlServerVersion.Version80 && typeof(Schema).IsAssignableFrom(smoObjectType))
			{
				Schema schema = smoObject as Schema;
				throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_SchemasNotSupportedOn2000, new object[]
				{
					schema.Name
				}));
			}
		}

		private static void CheckDatabaseRoles(ScriptingOptions scriptingOptions, SqlSmoObject smoObject, Type smoObjectType)
		{
			if (scriptingOptions.TargetServerVersion == SqlServerVersion.Version80 && typeof(DatabaseRole).IsAssignableFrom(smoObjectType))
			{
				DatabaseRole databaseRole = smoObject as DatabaseRole;
				if (scriptingOptions.TargetServerVersion == SqlServerVersion.Version80)
				{
					foreach (string current in databaseRole.EnumMembers())
					{
						if (current.Equals("sys", StringComparison.OrdinalIgnoreCase) || current.Equals("INFORMATION_SCHEMA", StringComparison.OrdinalIgnoreCase))
						{
							throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_DefaultUserNotSupportedOn2000, new object[]
							{
								databaseRole.Name,
								current
							}));
						}
					}
				}
			}
		}

		private static void CheckUDDTs(ScriptingOptions scriptingOptions, SqlSmoObject smoObject, Type smoObjectType)
		{
			if (scriptingOptions.TargetServerVersion != SqlServerVersion.Version80 || !typeof(UserDefinedDataType).IsAssignableFrom(smoObjectType))
			{
				return;
			}
			UserDefinedDataType userDefinedDataType = smoObject as UserDefinedDataType;
			bool flag = true;
			string text = userDefinedDataType.SystemType.ToLowerInvariant();
			string a;
			if ((a = userDefinedDataType.SystemType.ToLowerInvariant()) != null)
			{
				if (!(a == "nvarcharmax") && !(a == "varbinarymax") && !(a == "varcharmax"))
				{
					if (a == "nvarchar" || a == "varbinary" || a == "varchar")
					{
						if (userDefinedDataType.MaxLength == -1)
						{
							text = userDefinedDataType.SystemType.ToLower() + "max";
							flag = false;
						}
					}
				}
				else
				{
					flag = false;
				}
			}
			if (!flag)
			{
				throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_UDDTNotSupportedOn2000, new object[]
				{
					userDefinedDataType.Name,
					text
				}));
			}
		}

		private static void CheckUDF(ScriptingOptions scriptingOptions, SqlSmoObject smoObject, bool isSourceServerVesion2005, Type smoObjectType)
		{
			if (!typeof(UserDefinedFunction).IsAssignableFrom(smoObjectType))
			{
				return;
			}
			UserDefinedFunction userDefinedFunction = smoObject as UserDefinedFunction;
			if (isSourceServerVesion2005)
			{
				if (scriptingOptions.TargetServerVersion == SqlServerVersion.Version80 && userDefinedFunction.ExecutionContext != ExecutionContext.Caller)
				{
					throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_UDFExecuteAsNotSupportedInTargetVersion, new object[]
					{
						userDefinedFunction.Name,
						Enum.GetName(typeof(ExecutionContext), userDefinedFunction.ExecutionContext)
					}));
				}
				if (userDefinedFunction.ExecutionContext == ExecutionContext.ExecuteAsUser)
				{
					throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_UDFExecuteAsUserNotSupported, new object[]
					{
						userDefinedFunction.Name,
						Enum.GetName(typeof(ExecutionContext), userDefinedFunction.ExecutionContext)
					}));
				}
			}
			if (userDefinedFunction.ImplementationType != ImplementationType.SqlClr && userDefinedFunction.IsEncrypted)
			{
				throw new UnsupportedFeatureException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_ScriptingEncryptedUDF, new object[]
				{
					userDefinedFunction.Name
				}));
			}
		}

		private static void CheckStoredProcedures(bool isServerVersion2005, ScriptingOptions scriptingOptions, SqlSmoObject smoObject, Type smoObjectType)
		{
			if (!typeof(StoredProcedure).IsAssignableFrom(smoObjectType))
			{
				return;
			}
			StoredProcedure storedProcedure = smoObject as StoredProcedure;
			if (isServerVersion2005)
			{
				if (scriptingOptions.TargetServerVersion == SqlServerVersion.Version80 && storedProcedure.ExecutionContext != ExecutionContext.Caller)
				{
					throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_SPExecuteAsNotSupportedInTargetVersion, new object[]
					{
						storedProcedure.Name,
						Enum.GetName(typeof(ExecutionContext), storedProcedure.ExecutionContext)
					}));
				}
				if (storedProcedure.ExecutionContext == ExecutionContext.ExecuteAsUser)
				{
					throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_SPExecuteAsUserNotSupported, new object[]
					{
						storedProcedure.Name,
						Enum.GetName(typeof(ExecutionContext), storedProcedure.ExecutionContext)
					}));
				}
			}
			if (storedProcedure.ImplementationType != ImplementationType.SqlClr && storedProcedure.IsEncrypted)
			{
				throw new UnsupportedFeatureException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_ScriptingEncryptedStoredProc, new object[]
				{
					storedProcedure.Name
				}));
			}
		}

		private static void CheckTriggers(bool isSourceServerVesion2005, ScriptingOptions scriptingOptions, SqlSmoObject smoObject, Type smoObjectType)
		{
			Type typeFromHandle = typeof(Trigger);
			if (typeFromHandle.IsAssignableFrom(smoObjectType))
			{
				Trigger trigger = smoObject as Trigger;
				if (isSourceServerVesion2005)
				{
					if (scriptingOptions.TargetServerVersion == SqlServerVersion.Version80 && trigger.ExecutionContext != ExecutionContext.Caller)
					{
						throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_TriggerExecuteAsNotSupportedInTargetVersion, new object[]
						{
							trigger.Name,
							Enum.GetName(typeof(ExecutionContext), trigger.ExecutionContext)
						}));
					}
					if (trigger.ExecutionContext == ExecutionContext.ExecuteAsUser)
					{
						throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_TriggerExecuteAsUserNotSupported, new object[]
						{
							trigger.Name,
							Enum.GetName(typeof(ExecutionContext), trigger.ExecutionContext)
						}));
					}
				}
				if (trigger.ImplementationType != ImplementationType.SqlClr && trigger.IsEncrypted)
				{
					throw new UnsupportedFeatureException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_ScriptingEncryptedTrigger, new object[]
					{
						trigger.Name
					}));
				}
			}
			Type typeFromHandle2 = typeof(DatabaseDdlTrigger);
			if (typeFromHandle2.IsAssignableFrom(smoObjectType))
			{
				DatabaseDdlTrigger databaseDdlTrigger = (DatabaseDdlTrigger)smoObject;
				if (databaseDdlTrigger.IsEncrypted)
				{
					throw new UnsupportedFeatureException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_ScriptingEncryptedTrigger, new object[]
					{
						databaseDdlTrigger.Name
					}));
				}
				if (isSourceServerVesion2005)
				{
					if (scriptingOptions.TargetServerVersion == SqlServerVersion.Version80 && databaseDdlTrigger.ExecutionContext != DatabaseDdlTriggerExecutionContext.Caller)
					{
						throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_TriggerExecuteAsNotSupportedInTargetVersion, new object[]
						{
							databaseDdlTrigger.Name,
							Enum.GetName(typeof(DatabaseDdlTriggerExecutionContext), databaseDdlTrigger.ExecutionContext)
						}));
					}
					if (databaseDdlTrigger.ExecutionContext == DatabaseDdlTriggerExecutionContext.ExecuteAsUser)
					{
						throw new UnsupportedVersionException(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ERROR_TriggerExecuteAsUserNotSupported, new object[]
						{
							databaseDdlTrigger.Name,
							Enum.GetName(typeof(DatabaseDdlTriggerExecutionContext), databaseDdlTrigger.ExecutionContext)
						}));
					}
				}
			}
		}

		private Urn[] GetListOfObjectUrns(ScriptingOptions scriptingOptions)
		{
			Server server = new Server(this._serverConnection);
			server.SetDefaultInitFields(false);
			Database database = server.Databases[this.DatabaseName];
			TraceHelpers.TraceEnter(Logging.ScriptingEngineSwitch);
			if (this._urns != null && this._urns.Count > 0)
			{
				return this._urns.ToArray();
			}
			this.UpdateProgress(ScriptingEngineResources.IncludeDefaultObjects);
			List<Urn> urns = this.Urns;
			this._urns = urns;
			foreach (Table table in database.Tables)
			{
				if (!table.IsSystemObject)
				{
					urns.Add(table.Urn);
				}
			}
			if (!this.DataOnly)
			{
				urns.Add(database.Urn);
				foreach (UserDefinedFunction userDefinedFunction in database.UserDefinedFunctions)
				{
					if (!userDefinedFunction.IsSystemObject)
					{
						urns.Add(userDefinedFunction.Urn);
					}
				}
				foreach (Rule rule in database.Rules)
				{
					urns.Add(rule.Urn);
				}
				foreach (UserDefinedDataType userDefinedDataType in database.UserDefinedDataTypes)
				{
					urns.Add(userDefinedDataType.Urn);
				}
				foreach (StoredProcedure storedProcedure in database.StoredProcedures)
				{
					if (!storedProcedure.IsSystemObject)
					{
						urns.Add(storedProcedure.Urn);
					}
				}
				foreach (View view in database.Views)
				{
					if (!view.IsSystemObject)
					{
						urns.Add(view.Urn);
					}
				}
				foreach (Default @default in database.Defaults)
				{
					urns.Add(@default.Urn);
				}
				foreach (ApplicationRole applicationRole in database.ApplicationRoles)
				{
					urns.Add(applicationRole.Urn);
				}
				foreach (User user in database.Users)
				{
					if (!user.IsSystemObject)
					{
						urns.Add(user.Urn);
					}
				}
				UrnCollection urnCollection = new UrnCollection();
				foreach (DatabaseRole databaseRole in database.Roles)
				{
					if (!databaseRole.IsFixedRole && !databaseRole.Name.Equals("public", StringComparison.OrdinalIgnoreCase))
					{
						urnCollection.Add(databaseRole.Urn);
					}
				}
				this.AddDatabaseRoles(database, urnCollection, true);
				try
				{
					foreach (FullTextCatalog fullTextCatalog in database.FullTextCatalogs)
					{
						urns.Add(fullTextCatalog.Urn);
					}
				}
				catch (UnsupportedFeatureException)
				{
				}
				if (ScriptingDriver.IsServerVersionGreaterThan2000(database.Parent))
				{
					ScriptingDriver.AddSqlServer2005Objects(database, urns, scriptingOptions);
				}
			}
			return urns.ToArray();
		}

		internal void AddFullTextCatalog(Database database, UrnCollection selectedTables, UrnCollection selectedRoles)
		{
			Dictionary<string, FullTextCatalog> dictionary = new Dictionary<string, FullTextCatalog>();
			Dictionary<string, Urn> nameOfRolesAndUsers = this.GetNameOfRolesAndUsers(database);
			try
			{
				foreach (FullTextCatalog fullTextCatalog in database.FullTextCatalogs)
				{
					dictionary.Add(fullTextCatalog.Name, fullTextCatalog);
				}
			}
			catch (UnsupportedFeatureException)
			{
			}
			bool flag = ScriptingDriver.IsServerVersionGreaterThan2000(this.ServerObject);
			foreach (Urn current in selectedTables)
			{
				Table table = (Table)database.Parent.GetSmoObject(current);
				if (table.FullTextIndex != null)
				{
					FullTextCatalog fullTextCatalog2;
					dictionary.TryGetValue(table.FullTextIndex.CatalogName, out fullTextCatalog2);
					if (fullTextCatalog2 != null && !this.Urns.Contains(fullTextCatalog2.Name))
					{
						this.Urns.Add(fullTextCatalog2.Urn);
						if (flag)
						{
							Urn urn;
							nameOfRolesAndUsers.TryGetValue(fullTextCatalog2.Owner, out urn);
							if (urn != null && !this.Urns.Contains(urn))
							{
								if (urn.Type == "Role")
								{
									if (!selectedRoles.Contains(urn))
									{
										selectedRoles.Add(urn);
									}
								}
								else
								{
									this.Urns.Add(urn);
								}
							}
						}
					}
				}
			}
		}

		internal void AddDatabaseRoles(Database database, UrnCollection selectedRoles, bool withDependency)
		{
			Dictionary<string, Urn> nameOfRolesAndUsers = this.GetNameOfRolesAndUsers(database);
			foreach (Urn current in selectedRoles)
			{
				this.AddRole(database, selectedRoles, withDependency, nameOfRolesAndUsers, current);
			}
		}

		private void AddRole(Database database, UrnCollection selectedRoles, bool withDependency, Dictionary<string, Urn> namesOfRolesAndUsers, Urn roleUrn)
		{
			if (this.Urns.Contains(roleUrn) || roleUrn.Type != "Role")
			{
				return;
			}
			DatabaseRole databaseRole = (DatabaseRole)database.Parent.GetSmoObject(roleUrn);
			Urn urn;
			namesOfRolesAndUsers.TryGetValue(databaseRole.Owner, out urn);
			if (urn != null && (withDependency || selectedRoles.Contains(urn)))
			{
				this.AddRole(database, selectedRoles, withDependency, namesOfRolesAndUsers, urn);
			}
			this.Urns.Add(databaseRole.Urn);
		}

		private Dictionary<string, Urn> GetNameOfRolesAndUsers(Database database)
		{
			if (this._namesOfRolesAndUsers == null)
			{
				this._namesOfRolesAndUsers = new Dictionary<string, Urn>();
				foreach (DatabaseRole databaseRole in database.Roles)
				{
					if (!databaseRole.IsFixedRole)
					{
						this._namesOfRolesAndUsers.Add(databaseRole.Name, databaseRole.Urn);
					}
				}
				foreach (ApplicationRole applicationRole in database.ApplicationRoles)
				{
					this._namesOfRolesAndUsers.Add(applicationRole.Name, applicationRole.Urn);
				}
				foreach (User user in database.Users)
				{
					if (!user.IsSystemObject)
					{
						this._namesOfRolesAndUsers.Add(user.Name, user.Urn);
					}
				}
			}
			return this._namesOfRolesAndUsers;
		}

		private static bool IsServerVersionGreaterThan2000(Server server)
		{
			return server.Information.Version.Major > 8;
		}

		private static void AddSqlServer2005Objects(Database database, List<Urn> urns, ScriptingOptions scriptingOptions)
		{
			List<string> list = new List<string>();
			List<string> list2 = new List<string>();
			foreach (User user in database.Users)
			{
				if (user.IsSystemObject)
				{
					list.Add(user.Name);
				}
				else
				{
					list2.Add(user.Name);
				}
			}
			foreach (DatabaseRole databaseRole in database.Roles)
			{
				if (databaseRole.IsFixedRole)
				{
					list.Add(databaseRole.Name);
				}
				else
				{
					list2.Add(databaseRole.Name);
				}
			}
			foreach (ApplicationRole applicationRole in database.ApplicationRoles)
			{
				list2.Add(applicationRole.Name);
			}
			foreach (Schema schema in database.Schemas)
			{
				if (!list.Contains(schema.Name) && (scriptingOptions.TargetServerVersion != SqlServerVersion.Version80 || !list2.Contains(schema.Name)))
				{
					urns.Add(schema.Urn);
				}
			}
			foreach (DatabaseDdlTrigger databaseDdlTrigger in database.Triggers)
			{
				if (!databaseDdlTrigger.IsSystemObject)
				{
					urns.Add(databaseDdlTrigger.Urn);
				}
			}
			foreach (Synonym synonym in database.Synonyms)
			{
				urns.Add(synonym.Urn);
			}
			foreach (UserDefinedAggregate userDefinedAggregate in database.UserDefinedAggregates)
			{
				urns.Add(userDefinedAggregate.Urn);
			}
			foreach (XmlSchemaCollection xmlSchemaCollection in database.XmlSchemaCollections)
			{
				urns.Add(xmlSchemaCollection.Urn);
			}
			foreach (SqlAssembly sqlAssembly in database.Assemblies)
			{
				urns.Add(sqlAssembly.Urn);
			}
			foreach (UserDefinedType userDefinedType in database.UserDefinedTypes)
			{
				urns.Add(userDefinedType.Urn);
			}
		}

		private void InitializeOutputPath()
		{
			this._outputPath = this._serverConnection.DatabaseName + ".sql";
		}

		private void ConnectToServer()
		{
			this._serverConnection.StatementTimeout = 0;
			this._serverConnection.Connect();
			this.UpdateProgress(string.Format(CultureInfo.CurrentCulture, ScriptingEngineResources.ConnectedToDatabase, new object[]
			{
				this._serverConnection.DatabaseName,
				this._serverConnection.ServerInstance
			}));
		}

		private ScriptingOptions GetScriptingOptions()
		{
			return new ScriptingOptions
			{
				TargetServerVersion = this._targetServerVersion,
				AgentAlertJob = false,
				AgentJobId = false,
				AgentNotify = false,
				AllowSystemObjects = true,
				AnsiFile = false,
				AnsiPadding = false,
				AppendToFile = false,
				Bindings = true,
				ClusteredIndexes = true,
				ContinueScriptingOnError = false,
				ConvertUserDefinedDataTypesToBaseType = false,
				DdlBodyOnly = false,
				DdlHeaderOnly = false,
				Default = true,
				DriAll = false,
				DriAllConstraints = false,
				DriAllKeys = false,
				DriChecks = true,
				DriClustered = true,
				DriDefaults = true,
				DriForeignKeys = true,
				DriIncludeSystemNames = true,
				DriIndexes = true,
				DriNonClustered = true,
				DriPrimaryKey = true,
				DriUniqueKeys = true,
				DriWithNoCheck = false,
				EnforceScriptingOptions = true,
				ExtendedProperties = true,
				FullTextCatalogs = true,
				FullTextIndexes = true,
				IncludeDatabaseContext = false,
				IncludeHeaders = true,
				IncludeIfNotExists = true,
				Indexes = true,
				LoginSid = false,
				NoAssemblies = false,
				NoCollation = false,
				NoCommandTerminator = false,
				NoExecuteAs = false,
				NoFileGroup = true,
				NoIdentities = false,
				NoIndexPartitioningSchemes = true,
				NoMailProfileAccounts = true,
				NoMailProfilePrincipals = true,
				NonClusteredIndexes = true,
				NoTablePartitioningSchemes = true,
				NoViewColumns = false,
				NoXmlNamespaces = false,
				OptimizerData = false,
				Permissions = true,
				PrimaryObject = true,
				SchemaQualify = this._schemaQualify,
				SchemaQualifyForeignKeysReferences = this._schemaQualify,
				ScriptDrops = true,
				Statistics = false,
				TimestampToBinary = false,
				ToFileOnly = false,
				Triggers = true,
				WithDependencies = true,
				XmlIndexes = true
			};
		}
	}
}
